
package com.treasure.service.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.http.client.domain.UserInfo;
import com.treasure.service.collocate.service.GainStatisticsService;
import com.treasure.service.commons.lang.util.BeanUtil;
import com.treasure.service.commons.lang.util.IdCreater;
import com.treasure.service.commons.lang.util.PicUtil;
import com.treasure.service.commons.lang.util.StringUtil;
import com.treasure.service.commonutil.DrawingUtils;
import com.treasure.service.constant.Constants;
import com.treasure.service.constant.GlobalConstant;
import com.treasure.service.domain.*;
import com.treasure.service.dto.BizInformationPushForWechatOrSmsDto;
import com.treasure.service.dto.PrepareResult;
import com.treasure.service.dto.TUserInfoDto;
import com.treasure.service.dto.wechat.ActionInfo;
import com.treasure.service.dto.wechat.QRTicket;
import com.treasure.service.dto.wechat.Scene;
import com.treasure.service.enums.*;
import com.treasure.service.mapper.TMemberLogMapper;
import com.treasure.service.mapper.TRebateConfigMapper;
import com.treasure.service.mapper.TUserInfoMapper;
import com.treasure.service.mapper.TallyLogMapper;
import com.treasure.service.third.utils.RestClient;
import com.treasure.service.rabbit.service.SendMqService;
import com.treasure.service.result.ResponseResult;
import com.treasure.service.third.utils.TokenConfig;
import com.treasure.service.third.utils.UserToken;
import com.treasure.service.user.service.UserAccountService;
import com.treasure.service.user.service.UserInfoService;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.net.ssl.HttpsURLConnection;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
 * @author <a href="mailto:19919866605@163.com">Pan Xinwen</a>
 * @version 1.0 2018年5月29日 上午10:18:58
 */
@Service
public class UserServiceImpl implements UserInfoService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static ExecutorService executor = Executors.newFixedThreadPool(2);

    @Value("${treasure.rest.service.pay}")
    private String thirdUrl;

    @Autowired
    private TUserInfoMapper tUserInfoMapper;

	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Autowired
	private TMemberLogMapper tMemberLogMapper;

    @Autowired
    private TallyLogMapper tallyLogMapper;

	@Autowired
	private UserAccountService userAccountService;

	@Autowired
	private GainStatisticsService gainStatisticsService;

	@Autowired
	private TRebateConfigMapper tRebateConfigMapper;

	@Autowired
	private SendMqService sendMqService;

	@Autowired
	private RestClient restClient;

    @Value("${treasure.rest.service.pay}")
    private String payUrl;

    @Value("${mq.config.biz-Information-PushForWechatOrSms-key}")
    private String pushForWechatRoutingKey;

    @Override
    public int add(TUserInfo user) {
//        try {
//            user.setNickname(URLEncoder.encode(user.getNickname(), GlobalConstant.ENCODING_UTF8));
//        } catch (UnsupportedEncodingException e) {
//            logger.error("error{}",e);
//        }
        int count = tUserInfoMapper.insert(user);

        // Todo 生成推广图片
        executor.execute(()->{
            redisTemplate.opsForValue().set(RedisKeys.QRCODE.build("TICKET",user.getSelfInviteCode()), "100",60*10,TimeUnit.SECONDS);//设置邀请海报过期时间
            BufferedImage bufferedImage = getQRCode(user.getSelfInviteCode());
            try {
                DrawingUtils.getInviteCardImg("http://mobile.jingyugg.com/dist/index.html#/landing?inviteCode="+user.getSelfInviteCode(),bufferedImage,null,user.getSelfInviteCode());
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                DrawingUtils.getInviteVipImg("http://mobile.jingyugg.com/dist/index.html#/landing?inviteCode="+user.getSelfInviteCode(),null,user.getSelfInviteCode());
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                DrawingUtils.getInviteLoansImg("http://mobile.jingyugg.com/dist/index.html#/landing?inviteCode="+user.getSelfInviteCode(),bufferedImage,null,user.getSelfInviteCode());
            } catch (Exception e) {
                e.printStackTrace();
            }

        });

        //Todo 创建用户账户
        if (count == 1){
            userAccountService.createUserAccount(user.getUserId());
        }
        return 0;
    }

    @Override
    public TUserInfoDto getUserInfo(TUserInfo user) {

        tUserInfoMapper.selectOne(user);

        return BeanUtil.copy(tUserInfoMapper.selectOne(user),TUserInfoDto::new);
    }

    @Override
    public TUserInfo getUserInfoByUserId(Long userId) {

        TUserInfo info = tUserInfoMapper.selectByPrimaryKey(userId);

        return info;
    }


    @Override
    public TUserInfoDto updateUserInfo(TUserInfo user) {
//        try {
//            user.setNickname(URLEncoder.encode(user.getNickname(), GlobalConstant.ENCODING_UTF8));
//        } catch (UnsupportedEncodingException e) {
//            logger.error("error{}",e);
//            e.printStackTrace();
//        }
        tUserInfoMapper.updateByPrimaryKeySelective(user);
        TUserInfo tUserInfo = tUserInfoMapper.selectByPrimaryKey(user.getUserId());
        updateUserRedis(user.getUserId());
        return BeanUtil.copy(tUserInfo,TUserInfoDto::new);
    }

    @Override
    public PrepareResult dredgeMember(Long userId,Integer memberGrade,Long couponId,Integer payType,String clientIp) {

        TMemberLog tMemberLog = new TMemberLog();
        tMemberLog.setId(IdCreater.getLongId());
        tMemberLog.setUserId(userId);
        tMemberLog.setCreateTime(new Date());
        tMemberLog.setStatus(0);
        tMemberLog.setGrade(memberGrade);

        TUserInfo tUserInfo = tUserInfoMapper.selectByPrimaryKey(userId);
        Integer grade = tUserInfo.getGrade();
        logger.info("购买或升级会员查询当前用户的会员等级:userId===={},grade===={}",userId,grade);

        if (memberGrade<=grade){
            PrepareResult prepareResult = new PrepareResult();
            prepareResult.setReturn_code("500");
            return prepareResult;
        }

        if (grade.intValue() > 0 && grade.intValue() <= 3){
            tMemberLog.setAmount(MemberEnum.getPrice(memberGrade)-MemberEnum.getPrice(grade));
            logger.info("当前用户已经是付费会员：{}，升级会员等级：{}，当前需补差价：{}",grade,memberGrade,tMemberLog.getAmount());
        }else {
            tMemberLog.setAmount(MemberEnum.getPrice(memberGrade));
            logger.info("当前用户是普通用戶：{}，升级会员等级：{}，需付費金額：{}",grade,memberGrade,tMemberLog.getAmount());
        }

        /**
         * 判断是否使用优惠券
         */
        if (!StringUtil.isEmpty(couponId)){

        }
        PrepareResult prepareResult = null;

        if (tMemberLogMapper.insert(tMemberLog)==1){

            //调用支付
            Map<String,Object> map = new HashMap<>();
            map.put("payType",payType);
            map.put("bizId",tMemberLog.getId());
            map.put("amount",tMemberLog.getAmount()==null?1l:tMemberLog.getAmount());
            map.put("bizType",PayEnum.BUY_MEMBER.getCode());
            map.put("userId",userId);
            map.put("clientIp",clientIp);

            prepareResult = restClient.post(payUrl+"/pay/v1/charge",map,PrepareResult.class);

        }else {
            prepareResult.setResult_code("error");
        }
        return prepareResult;
    }

    @Override
    public void dredgeMemberCallBack(Long bizId,Long userId, Integer status) {

        TMemberLog tMemberLog = tMemberLogMapper.selectByPrimaryKey(bizId);
        tMemberLog.setStatus(status);
        tMemberLog.setUpdateTime(new Date());

        if (status == 1){
            TUserInfo tUserInfo = tUserInfoMapper.selectByPrimaryKey(userId);
            tUserInfo.setIsMember(status);
            tUserInfo.setGrade(tMemberLog.getGrade());
            int count = tUserInfoMapper.updateByPrimaryKeySelective(tUserInfo);
            updateUserRedis(tUserInfo.getUserId());
            if (count == 1){
                //TODO 公众号或短信推送用户开通或升級会员成功
                BizInformationPushForWechatOrSmsDto bizInformationPushForWechatOrSmsDto = new BizInformationPushForWechatOrSmsDto();
                bizInformationPushForWechatOrSmsDto.setUserId(userId);
                bizInformationPushForWechatOrSmsDto.setBizType(PushEnum.BUY_MEMBER.getBizType());
                bizInformationPushForWechatOrSmsDto.setPushType(PushEnum.BUY_MEMBER.getPushType());
                bizInformationPushForWechatOrSmsDto.setObject(tMemberLog);
                bizInformationPushForWechatOrSmsDto.setSocket(MemberEnum.getIntroduce(tUserInfo.getGrade()));
                sendMqService.sendMsgServiceJson(pushForWechatRoutingKey,bizInformationPushForWechatOrSmsDto);
            }

            // Todo 办理会员成功后统计邀请人返佣
            if (StringUtil.isNotEmpty(tUserInfo.getInviteCode())){

                TUserInfo inviter = tUserInfoMapper.selectByPrimaryKey(tUserInfo.getInviteCode());
                if (inviter.getGrade().intValue() > 0){
                    TRebateConfig tRebateConfig = tRebateConfigMapper.selectOne(new TRebateConfig());
                    Long rate=0l;
                    if (inviter.getGrade().intValue() == 1){
                        rate = tRebateConfig.getvInviteVipRate();
                    }
                    if (inviter.getGrade().intValue() == 2){
                        rate = tRebateConfig.getfInviteVipRate();
                    }
                    if (inviter.getGrade().intValue() == 3){
                        rate = tRebateConfig.getGfInviteVipRate();
                    }
                    Long amount = tMemberLog.getAmount()*rate/100;

                    TallyLog tallyLog = new TallyLog();
                    logger.info("下级成为会员获得返佣，上级=={},userid={},amount",tUserInfo.getUserId(),inviter.getUserId(),amount);
                    //Todo 记账
                    tallyLog.setId(IdCreater.getLongId());
                    tallyLog.setAcquireId(inviter.getUserId());
                    tallyLog.setAmount(amount);
                    tallyLog.setAppointAmount(0l);
                    tallyLog.setAppointApr(rate);
                    tallyLog.setCreateTime(new Date());
                    tallyLog.setModifyTime(new Date());
                    tallyLog.setOrderId(tMemberLog.getId());
                    tallyLog.setType(Constants.InviteType.CHILD_CTRANSACTION_MEMBER);
                    tallyLog.setUserId(tUserInfo.getUserId());
                    tallyLog.setAcquireGrade(inviter.getGrade());

                    tallyLogMapper.insert(tallyLog);
                    Map<String,String> map = new HashMap<>();
                    map.put("type",tallyLog.getType()+"");
                    map.put("amount",amount+"");
                    map.put("userId",inviter.getUserId()+"");
                    map.put("orderId",tallyLog.getId()+"");

                    Integer result = restClient.post(thirdUrl+"/tally/v1/tally",map,Integer.class);

                    //Todo 更新今日邀请会员
                    gainStatisticsService.calculatePrice(userId,GainEnum.INVITE_VIP.getCode(),tallyLog.getAmount());
                }


            }

        }


        tMemberLogMapper.updateByPrimaryKeySelective(tMemberLog);

    }

    @Override
    public void bindingRelation(String openId, String inviteCode) throws UnsupportedEncodingException {

        TUserInfo user = new TUserInfo();
        user.setOpenId(openId);
        user = tUserInfoMapper.selectOne(user);

        if (user == null || user.getOpenId()==null){
            user = new TUserInfo();
            user.setUserId(IdCreater.getLongId());
//            user.setNickname(user.getNickname());
//            user.setwNickname(user.getNickname());
            user.setJoinTime(new Date());
            user.setLastLoginTime(new Date());
            user.setIsAttention(1);
            user.setIsAuthName(false);
            user.setIsBindingBankcard(false);
            user.setIsSetPayPwd(false);
            user.setIsBindingEmail(false);
            user.setStatus(1);
            //TODO 生成邀请码
            long currentAmt = redisTemplate.opsForValue().increment(RedisKeys.INVITE_CODE.build(), 1)+1000000l;
            user.setSelfInviteCode(currentAmt+"");

            // TODO 通过邀请码获取邀请人信息
            inviteCode=inviteCode.split("_")[1];
            TUserInfo tUserInfo = new TUserInfo();
            tUserInfo.setSelfInviteCode(inviteCode);
            tUserInfo = tUserInfoMapper.selectOne(tUserInfo);

            user.setInviteCode(tUserInfo.getUserId());
            tUserInfoMapper.insert(user);
        }

    }

    @Override
    public void statisticsIntegral(Long price, Long userId, Integer... type) {

        Long value=0l;
        for (Integer t:type) {
            switch (t){

                case 41://挣取收益(一元收益兑换一积分)
                    value=price;
                    break;
                case 42://推荐办理信用卡
                    value=2l;
                    break;
                case 43://邀请会员
                    value=5l;
                case 44://锁粉

                default:
                    break;

            }
        }

        TUserInfo tUserInfo =  tUserInfoMapper.selectByPrimaryKey(userId);

        if (tUserInfo.getGrade() < 2){
            logger.info("还未升级到创业者，不累计财富值:userId{}",userId);
            return;
        }

        tUserInfo.setWealthValue(tUserInfo.getWealthValue()+value);

        if (tUserInfo.getWealthValue().intValue()>=3000){
            tUserInfo.setGrade(3);
        }

        tUserInfoMapper.updateByPrimaryKeySelective(tUserInfo);
        updateUserRedis(tUserInfo.getUserId());

    }

    @Override
    public TUserInfo bindingPhonenumber(String phonenumber, Long userId) {

        TUserInfo userInfo = tUserInfoMapper.selectByPrimaryKey(userId);
        userInfo.setPhonenumber(phonenumber);
        tUserInfoMapper.updateByPrimaryKeySelective(userInfo);
        updateUserRedis(userInfo.getUserId());
        return  userInfo;

    }

    @Override
    public ResponseResult perfectInfo(TUserInfo user) {

        //Todo 查询用户信息
        TUserInfo suser = new TUserInfo();
        suser.setCardNumber(user.getCardNumber());
        TUserInfo userInfo = tUserInfoMapper.selectOne(suser);
        if (userInfo != null && StringUtil.isNotEmpty(userInfo.getUserId())){
            return new ResponseResult(CodeEnum.IDENTITY_REPETITION);
        }else {
            user.setIsAuthName(true);
            tUserInfoMapper.updateByPrimaryKeySelective(user);
            updateUserRedis(user.getUserId());
        }

        return new ResponseResult();
    }

    @Override
    public void removeUserInfo(Long userId) {
        tUserInfoMapper.deleteByPrimaryKey(userId);
    }

//    // Todo 生成公众号二维码
//    private BufferedImage getQRCode(String selfInviteCode) {
//
//        String ticket=redisTemplate.opsForHash().get(RedisKeys.QRCODE.build("TICKET"),selfInviteCode)+"";
//
//        logger.info("缓存中二维码获取ticket："+ticket);
//
//
//        if (StringUtil.isEmpty(ticket)){
//
//            QRTicket qrTicket = new QRTicket();
//            qrTicket.setExpire_seconds(2592000);
//            Scene scene = new Scene();
//            scene.setScene_id(Long.parseLong(selfInviteCode));
//            ActionInfo actionInfo = new ActionInfo();
//            actionInfo.setScene(scene);
//            qrTicket.setAction_info(actionInfo);
//
//            AccessToken accessToken = JSON.parseObject((String) redisTemplate.opsForHash().get(RedisKeys.ACCESS_TOKEN.build(""), "access_token"),AccessToken.class);
//
//            String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken.getAccessToken();
//            String is = restClient.post(url,qrTicket,String.class);
//            JSONObject jsonObject = JSON.parseObject(is);
//
//            logger.info("获取邀请二维码第一步生成ticket：{}",jsonObject);
//            ticket = jsonObject.getString("ticket");
//            redisTemplate.opsForHash().put(RedisKeys.QRCODE.build("TICKET"),selfInviteCode,ticket);
//            redisTemplate.expire(RedisKeys.QRCODE.build("TICKET"), 2592000, TimeUnit.SECONDS); //设置超时时间10秒 第三个参数控制
//            return getRQcode(ticket);
//        }
//
//        return null;
//    }
//    public BufferedImage getRQcode(String ticket)
//    {
//        try
//        {
//            String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+URLEncoder.encode(ticket, GlobalConstant.ENCODING_UTF8);
//            URL url = new URL(requestUrl);
//            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//            conn.setDoInput(true);
//            conn.setRequestMethod("GET");
//
//            // 将微信服务器返回的输入流写入文件
//            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
//            BufferedImage bufferedImage = ImageIO.read(bis);
//            logger.info("根据ticket换取二维码成功");
//            return bufferedImage;
//        } catch (Exception e)
//        {
//            logger.error("根据ticket换取二维码失败", e);
//        }
//
//        return null;
//
//    }

    public BufferedImage getQRCode(String selfInviteCode) {

        String ticket=redisTemplate.opsForHash().get(RedisKeys.QRCODE.build("TICKET"),selfInviteCode)+"";

        logger.info("缓存中二维码获取ticket："+ticket);

        String filePath = "/data/static/img/RQcode/" + selfInviteCode + ".jpg";

        if (StringUtil.isEmpty(ticket)){

            File file=new File(filePath);
            if(file.exists()&&file.isFile())file.delete();

            QRTicket qrTicket = new QRTicket();
            qrTicket.setExpire_seconds(2592000);
            Scene scene = new Scene();
            scene.setScene_id(Long.parseLong(selfInviteCode));
            ActionInfo actionInfo = new ActionInfo();
            actionInfo.setScene(scene);
            qrTicket.setAction_info(actionInfo);

            AccessToken accessToken = JSON.parseObject((String) redisTemplate.opsForHash().get(RedisKeys.ACCESS_TOKEN.build(""), "access_token"),AccessToken.class);

            String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken.getAccessToken();
            String is = restClient.post(url,qrTicket,String.class);
            JSONObject jsonObject = JSON.parseObject(is);

            logger.info("获取邀请二维码第一步生成ticket：{}",jsonObject);
            ticket = jsonObject.getString("ticket");
            try {
                return  ImageIO.read(new FileInputStream(getRQcode(ticket,selfInviteCode)));
            } catch (IOException e) {
                e.printStackTrace();
            }
            ;
        }

        return null;
    }

    public  String getRQcode(String ticket,String selfInviteCode)
    {
        String filePath = "/data/static/img/RQcode/" + ticket + ".jpg";
        try
        {
            String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+URLEncoder.encode(ticket, GlobalConstant.ENCODING_UTF8);
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setDoInput(true);
            conn.setRequestMethod("GET");

            // 将微信服务器返回的输入流写入文件
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            FileOutputStream fos = new FileOutputStream(new File(filePath));

            byte[] buf = new byte[8096];
            int size = 0;
            while ((size = bis.read(buf)) != -1)
                fos.write(buf, 0, size);
            fos.close();
            bis.close();

            conn.disconnect();

            //缩放
            PicUtil.zoomImage(filePath,"/data/static/img/RQcode/" + selfInviteCode + "s.jpg",124,124);
            File file=new File(filePath);
            if(file.exists()&&file.isFile())file.delete();
            filePath="/data/static/img/RQcode/" + selfInviteCode + "s.jpg";

            logger.info("根据ticket换取二维码成功");
        } catch (Exception e)
        {
            filePath = null;
            logger.error("根据ticket换取二维码失败", e);
        }

        return filePath;

    }

    public void  testStream(){
        Stream.generate(new PersonSupplier()).limit(20).forEach(
                person -> System.out.println(person.getAge()+","+person.getName())
        );
    }

    public class PersonSupplier implements Supplier<Person>{

        private int index =0;

        private Random random=new Random();

        @Override
        public Person get() {
            return new Person(index++,"小明"+index,random.nextInt(1000));
        }
    }

    @Data
    @NoArgsConstructor
    public class Person{

        private int index;

        private String name;

        private int age;

        public Person(int index,String name,int age){

        }

    }

    private void updateUserRedis(Long userId){

        TUserInfo userInfo = tUserInfoMapper.selectByPrimaryKey(userId);
        UserToken userToken = BeanUtil.copy(userInfo,UserToken::new);
        TokenConfig.updateToken(userToken);

    }

}

